package com.blog.service.Impl;

import com.alibaba.fastjson.JSON;
import com.blog.Event.EventMsgDomain;
import com.blog.SystemMsg.SystemMsgProducer;
import com.blog.Utils.RedisKeyUtil;
import com.blog.bean.domain.User;
import com.blog.mapper.UserMapper;
import com.blog.service.AttentionService;
import com.blog.bean.vo.UserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author 任浩
 * @version 1.0
 */

@Service
public class AttentionServiceImpl implements AttentionService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SystemMsgProducer systemMsgProducer;
    @Autowired
    private EventMsgDomain eventMsgDomain;
    /**
     * 添加关注
     * @param id
     * @param userId
     */
    @Override
    @Transactional
    public Integer addAttition(Integer id, Integer userId) {
        //对当前用户的关注进行操作。
        //使用当前的用户的id作为用户的关注的key.
        String attentionKey = RedisKeyUtil.attention(userId.toString());
        //使用关注的用户的id作为值。
        //使用当前的时间作为分数值。
        long score = System.currentTimeMillis();
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        //对当前用户进行判断，是否存在已关注，如果是已关注那么，就取消关注。
        Double score1 = zSetOperations.score(attentionKey, id);

        if(score1 != null){  //当前用户已存在关注，那么进行删除
            zSetOperations.remove(attentionKey,id);

            /**
             * 继续对当前关注的用户的粉丝列表进行操作。
             * 使用当前的用户关注的用户id，作为key，当前用户id作为value，当前的时间作为分数。
             */
            String fansKey = RedisKeyUtil.fans(id.toString());
            zSetOperations.remove(fansKey,userId);
            return 0;
        }
        //进行添加操作。
        Boolean add = zSetOperations.add(attentionKey, id, score);
        if(!add){
            throw new  RuntimeException("redis保存关注数据操作失败");
        }
        /**
         * 继续对当前关注的用户的粉丝列表进行操作。
         * 使用当前的用户关注的用户id，作为key，当前用户id作为value，当前的时间作为分数。
         */
        String fansKey = RedisKeyUtil.fans(id.toString());
        score = System.currentTimeMillis();
        add = zSetOperations.add(fansKey, userId, score);

        //对关注的信息，存放到系统的消息中。
        eventMsgDomain.setFromId(1);
        eventMsgDomain.setUserid(userId);
        eventMsgDomain.setConversationId("attention");
        eventMsgDomain.setEntity_type(3);
        eventMsgDomain.setToId(id); //这是使用关注的用户的id作为值。

        String msg = JSON.toJSONString(eventMsgDomain);

        systemMsgProducer.producer(msg);

        if(!add){
            throw new  RuntimeException("redis保存粉丝数据操作失败");
        }
        return 1;
    }

    /**
     * 得到当前用户的关注数
     * @param userId
     * @return
     */
    @Override
    public Long getAttention(Integer userId) {
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        String attentionKey = RedisKeyUtil.attention(userId.toString());
        Long size = zSetOperations.size(attentionKey);

        return size;
    }

    /**
     * 得到用户的粉丝数
     * @param userId
     * @return
     */
    @Override
    public Long getFans(Integer userId) {
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        String attentionKey = RedisKeyUtil.fans(userId.toString());
        Long size = zSetOperations.size(attentionKey);

        return size;
    }

    /**
     * 查看详情的用户是否已被关注。
     * @param userId
     * @param currentUserId
     * @return
     */
    @Override
    public String getUserIsAttention(Integer userId, Integer currentUserId) {
        //对当前用户的关注进行操作。
        //使用当前的用户的id作为用户的关注的key.
        String attentionKey = RedisKeyUtil.attention(currentUserId.toString());
        //使用关注的用户的id作为值。
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        //对当前用户进行判断，是否已关注
        Double score = zSetOperations.score(attentionKey, userId);

        if(score == null){
            //未关注
            return "关注TA";
        }
        else {
            return "已关注";
        }
    }

    /**
     * 得到用户的关注列表
     * @param id
     * @return
     */
    @Override
    public Map<String, Object> getAttentionList(Integer id, Integer currentUserId, Integer page, Integer pageNum) {
        List<UserVO> list = new ArrayList<>();
        //查询当前的用户列表。
        //先计算出要查询的偏移量，
        //开始的偏移量为：(page-1) * 10   结束的偏移量，为(page-1) * 10 +pageNum -1
        //得到当前用户的关注列表的key
        String attentionKey = RedisKeyUtil.attention(id.toString());
        long start = (page-1)*10;
        long end = start + pageNum -1;
        /**
         * 把当前值按照存入的时间倒序排序，因为我们存入的score就是时间的值
         */
        Set set = redisTemplate.opsForZSet().reverseRange(attentionKey, start, end);

        //如果当前查询的值为0，则直接返回为null。
        if(set == null){
            return null;
        }

        for (Object o : set) {
            //根据得到存入的value，就是用户的id值。得到用户的信息。
            Integer userId = (Integer) o;
            User user = new User();
            user.setId(userId);
            user = userMapper.check(user);
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(user,userVO);

            //查看当前用户是否被被人关注的用户。
            //如果当前查看的用户的关注列表，和当前用户id一样，那就是查看自己的关注列表。那么就直接全部用户关注都是已关注。
            if(id == currentUserId){
                userVO.setAttentionMsg("已关注");
            }
            else {
                String userIsAttention = getUserIsAttention(userId, currentUserId);
                userVO.setAttentionMsg(userIsAttention);
            }
            list.add(userVO);
        }

        Map<String ,Object> map = new HashMap<>();
        map.put("attentionData",list);
        //查询一个有多少关注用户或者粉丝用户的信息。
        Long size = redisTemplate.opsForZSet().size(attentionKey);
        map.put("size",size);
        //设置当前页面
        map.put("curPage",page);

        return map;
    }

    /**
     *  得到用户粉丝的关注列表
     * @param id
     * @param currentuserId
     * @param page
     * @param pageNum
     * @return
     */
    @Override
    public Map<String, Object> getFansList(Integer id, Integer currentuserId, int page, int pageNum) {
        List<UserVO> list = new ArrayList<>();

        //查询当前的用户列表。
        //先计算出要查询的偏移量，
        //开始的偏移量为：(page-1) * 10   结束的偏移量，为(page-1) * 10 +pageNum -1
        //得到当前用户的关注列表的key
        String attentionKey = RedisKeyUtil.fans(id.toString());
        long start = (page-1)*10;
        long end = start + pageNum -1;
        /**
         * 把当前值按照存入的时间倒序排序，因为我们存入的score就是时间的值
         */
        Set set = redisTemplate.opsForZSet().reverseRange(attentionKey, start, end);

        //如果当前查询的值为0，则直接返回为null。
        if(set == null){
            return null;
        }

        for (Object o : set) {
            //根据得到存入的value，就是用户的id值。得到用户的信息。
            Integer userId = (Integer) o;
            User user = new User();
            user.setId(userId);
            user = userMapper.check(user);
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(user,userVO);

            //查看当前用户的粉丝是否被自己所关注。
            //如果当前查看的用户的关注列表，和当前用户id一样，那就是查看自己的关注列表。那么就直接全部用户关注都是已关注。
            if(id == currentuserId){
                userVO.setAttentionMsg("已关注");
            }
            else {
                String userIsAttention = getUserIsAttention(userId, currentuserId);
                userVO.setAttentionMsg(userIsAttention);
            }
            list.add(userVO);
        }

        Map<String ,Object> map = new HashMap<>();
        map.put("fansData",list);
        //查询一个有多少关注用户或者粉丝用户的信息。
        Long size = redisTemplate.opsForZSet().size(attentionKey);
        map.put("size",size);
        //设置当前页面
        map.put("curPage",page);

        return map;
    }
}
